module mculib.arm.cortex_m;

//version(None):

import core.attribute;
//import ldc.intrinsics;
import mculib.baremetal;

public import mculib.arm.stk;
public import mculib.arm.scb;
public import mculib.arm.scs;
public import mculib.arm.nvic;
public import mculib.arm.hal;
public import mculib.arm.tpi;




package{

}

/// Cortex-M4 优先级占位宽度
enum PriorityWidth = 4U;




/// cortex-mx 通用中断向量表
enum IRQn_Core 
{
    NonMaskableInt_IRQn = -14,          /// 不可屏蔽中断   
    MemoryManagement_IRQn = -12,        /// 内存管理中断
    BusFault_IRQn = -11,                /// 总线错误中断
    UsageFault_IRQn = -10,              /// 调用错误中断
    SVCall_IRQn = -5,                   /// 调用中断
    DebugMonitor_IRQn = -4,             /// 调试监视中断
    PendSV_IRQn = -2,                   /// 挂起中断
    SysTick_IRQn = -1,                  /// 系统时间中断
}

/// cortex-mx 通用中断向量表
enum VectorCore : uint
{
    SP = 0,
    Reset,
    NMI,
    HardFault,
    MemManage,
    BusFault,
    UsageFault,
    SVC = 11,
    DebugMon,
    PendSV = 14,
    SysTick
}

alias CallHandler = void function();
alias VectorFunc = extern(C) void *;

/// cortex-m 通用中断向量表
enum VectorFunc[] Cortex_M = [
    VectorCore.SP:cast(VectorFunc)&_estack,
    VectorCore.Reset: &Reset_Handler,
    VectorCore.NMI: &NMI_Handler,
    VectorCore.HardFault: &HardFault_Handler,
    VectorCore.MemManage: &MemManage_Handler,
    VectorCore.BusFault: &BusFault_Handler,
    VectorCore.UsageFault: &UsageFault_Handler,
    VectorCore.SVC: &SVC_Handler,
    VectorCore.DebugMon: &DebugMon_Handler,
    VectorCore.PendSV: &PendSV_Handler,
    VectorCore.SysTick: &SysTick_Handler,
];

//@naked
@weak
pragma(LDC_extern_weak)
extern
extern(C)  __gshared
{
    void NMI_Handler();
    void HardFault_Handler();
    void MemManage_Handler();
    void BusFault_Handler();
    void UsageFault_Handler();
    void SVC_Handler();
    void DebugMon_Handler();
    void PendSV_Handler();
    void SysTick_Handler();
}


/// 用户主函数调用
extern(C) extern void mloop();

private
extern
extern(C) __gshared
{
    /// Init SP
    void* _estack ;

    /// data 段,初始化值
    void*   __data_loadaddr,__data_start,__data_end;
    void*  __data_size;


    /// bss 段, 初始化内存
    void*   __bss_loadaddr,__bss_loadend;

    /// tbss 段, 初始化内存
    extern __gshared void* __tbss_start__,__tbss_size__,__tbss_end__;

    /// init 段
    void*   __preinit_array_start,__preinit_array_end;
    void*   __init_array_start,__init_array_end;
    void*   __fini_array_start,__fini_array_end;
    void*  __preinit_array_size,__init_array_size,__fini_array_size;
}

@naked 
extern(C) 
@noreturn void Reset_Handler()  
{

    //import ldc.llvmasm;
    //__asm("ldr sp,=_estack","");
    asm{
        "ldr sp,=_estack";
    }

    // 复制data到内存
    copyBlock(&__data_loadaddr,&__data_start,&__data_end);
    
    // 复制tdata到内存
    //copyBlock(&__stdata_loadaddr__,&__tdata_start__,&__tdata_end__);


    // 初始化bss
    zeroBlock(&__bss_loadaddr,&__bss_loadend);

    // 初始化tbss
    //zeroBlock(&__tbss_start__,&__tbss_end__);

    /// 初始化fpu
    



    //初始化函数执行
    execSection(&__preinit_array_start,&__preinit_array_end);
    // 执行模块初始化函数
    execSection(&__init_array_start,&__init_array_end);

    // 主循环体
    mloop();
    // 释放模块函数
    execSection(&__fini_array_start,&__fini_array_end);

    //维持错误状态下循环
    while(1){
        
    }
    
    
}


//---------------------------------------------------------------------
//extern(C)
private
{
    //---------------------------------------------------------------------
    /// 初始化内存
    //pragma(inline,true)
    //@optStrategy("none")
    void copyBlock(const(void) *aSource, void *aDestination, void *aDestinationEnd)
    {
        auto    s = cast(const(size_t) *)aSource;
        auto    d = cast(size_t *)aDestination;
        auto    e = cast(size_t *)aDestinationEnd;

        while(d < e)
        {
            *d++ = *s++;
        }
    }

    /// 内存初始化
    //pragma(inline,true)
    //@optStrategy("none")
    void zeroBlock(void* aDestination,void* aDestinationEnd)
    {
        auto	d = cast(size_t *)aDestination;
        auto    e = cast(size_t *)aDestinationEnd;

        while(d < e)
        {
            *d++ = 0x00;
        }
    }

    ///init段处理
    void execSection(void* start,void* end)
    {
        //alias vfun = void function();
        auto s = cast(CallHandler*)start;
        auto e = cast(CallHandler*)end;

        while(cast(size_t)s < cast(size_t)e)
        {
            (*s++)();
        }
    }
    //---------------------------------------------------------------------
}


